#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <cstring>
#include "Commend.hpp"
#include "UdpAddr.hpp"
static const std::string glocalip = "0";

using namespace log_ns;
class udpserver
{

public:
    udpserver(u_int16_t localport)
        : _local_port(localport), _local_ip(glocalip), _isrunning(false), _sockfd(-1)
    {
    }
    ~udpserver() {}

    void InitServer()
    {
        // 申请套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(FATAL, "<server> socket error,error information: %s\n", strerror(errno));
            exit(APPLY_SOCKET_ERROR);
        }
        LOG(DEBUG, "<server> socket application success\n");
        sockaddr_in inaddr;
        memset(&inaddr, 0, sizeof(inaddr));
        inaddr.sin_family = AF_INET;
        inaddr.sin_port = htons(_local_port);
        inaddr.sin_addr.s_addr = inet_addr(_local_ip.c_str());
        // 绑定套接字

        int n = bind(_sockfd, (sockaddr *)&inaddr, sizeof(inaddr));

        if (n < 0)
        {
            LOG(FATAL, "<server> bind error,error information: %s\n", strerror(errno));
            exit(SOCKET_BIND_ERROR);
        }
        LOG(DEBUG, "<server> bind success, ip: %s, port: %d\n", _local_ip.c_str(), _local_port);
    }
    void Start()
    {
        _isrunning = true;
        char buffer[1024];
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        while (_isrunning)
        {
            // 接受消息
            int n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&addr, &len);
            if (n < 0)
            {
                LOG(FATAL, "<server> revcfrom error, error infomation: %s\n", strerror(errno));
                exit(RECVFORM_ERROR);
            }
            else
            {
                buffer[n] = 0;
                LOG(DEBUG, "<server> revcfrom infomation: %s\n", buffer);
            }

            std::string message = buffer;
            addr_t who(addr);
            std::cout << "[" << who.Ip() << ": " << who.Port() << "]# " << message << std::endl;
            message = "[server return]#" + message;
            sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)who.Addr(), who.Len());
        }

        ::close(_sockfd);
    }

private:
    int _sockfd;
    u_int16_t _local_port;
    std::string _local_ip;

    bool _isrunning;
};